/* clientMail.c */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <time.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/stat.h>
#include <signal.h>
#include <semaphore.h>
#include <unistd.h>
#include <dirent.h>

#define fflush(stdin) while ((getchar()) != '\n')

#define porta 3666

/* Costanti di acknoledge */
#define ACK "accept"

#define NACK "refuse"

int creaSocket(char* Destinazione, int Porta){
	struct sockaddr_in temp;
	struct hostent *h;
	int sock;
	int errore;

	/*Tipo di indirizzo*/
	temp.sin_family=AF_INET;
	temp.sin_port=htons(Porta);
	h=gethostbyname(Destinazione);
	if (h==0){
		perror("ERROR: Gethostbyname fallito");
		exit(1);
	}
	bcopy(h->h_addr,&temp.sin_addr,h->h_length);
	/*Creazione socket*/
	sock=socket(AF_INET,SOCK_STREAM,0);
	/*Connessione del socket. Esaminare errore per compiere azioni
	 *opportune in caso di errore*/
	errore=connect(sock, (struct sockaddr*) &temp, sizeof(temp));
	return sock;

}

void chiudiSocket(int sock){
	close(sock);
	return;

}

void spedisciMessaggio(int sock, char* Messaggio){
  short int N;
  N=contaChar(Messaggio)+1;
  if (send(sock,(short int*)&N,sizeof(short int),0)<0){
		perror("Error: Impossibile mandare il messaggio.");
		chiudiSocket(sock);
		exit(1);

  }
  if (send(sock,Messaggio,strlen(Messaggio)+1,0)<0){
		perror("Error: Impossibile mandare il messaggio.");
		chiudiSocket(sock);
		exit(1);

	}
	return;

}

void login(char* user, char* psw){
	printf("Inserisci username:\n");
	scanf("%s",user);
	printf("Inserisci password:\n");
	scanf("%s",psw);
        return;
}

void riceviMessaggi(int sock){
	FILE *fp;
	short int N=1;
	time_t rawtime;
	time (&rawtime);
	struct tm* leggibile;
	char mitt[65],*msg=NULL,*ptr,fileName[128],data[64];

	while(N>0){
		/* Leggo la dimensione del messaggio */
		recv(sock,(short int*)&N,sizeof(short int),0);

		N=ntohs(N);

		/* Salvo in un puntatore d'appoggio l'indirizzo di buff, in modo da poterlo recuperare se la riallocazione non dovesse andare a buon fine */
		ptr=msg;

		/* Alloco memoria per ricevere la stringa */

		msg=(char*)realloc(msg,N*sizeof(char));

		/* Verifico che l'allocazione sia andata a buon fine */
		if(msg==NULL){
			/* Dealloco lo spazio precedentemente assegnato a buff */
			free(ptr);
			perror("ERROR on realloc");
			exit(1);
		}

		/* Ricevo il messaggio */
		recv(sock,msg,N*sizeof(char),0);

			fileName[0]='\0';

		/* Recupero la data del sistema */
		leggibile = localtime(&rawtime);

		/* Salvo in una stringa la data nel formato dd-mm-yyyy_hh:mm */
		sprintf(data,"%d-%d-%d_%d:%d",leggibile->tm_mday,leggibile->tm_mon,leggibile->tm_year,leggibile->tm_hour,leggibile->tm_min);

		recuperaMittente(msg,&mitt[0]);
		strcat(strcat(fileName,data),mitt);

		/* Apro il file in scrittura */
		fp=fopen(fileName,"w");

		/* Copio nel file il contenuto del messaggio */
		fprintf(fp,"%s",msg);

		/* Chiudo il file */
		fclose(fp);

	}

  return;
}


int gestione_dir(){
	mkdir("mailBox",S_IRWXU);
	chdir("mailBox");
	return 0;

}


/* Conta i caratteri di una stringa  */
int contaChar(char* stringa){
	int i=0;
	while(stringa[i]!='\0')i++;
	return i+1;

}

int recuperaMittente(char* messaggio,char* mitt){
  int i=8,j=0;
  while(messaggio[i]!='\n'){
    i++;
  }
  i=i+10;
    while(messaggio[i]!='\n'){
      mitt[j]=messaggio[i];
      j++;
      i++;
  }
  mitt[j]='\0';
}

int main(int argc, char* argv[]){
	char user[65],psw[65],messaggio[130],server[16],buffer[512],stringa[65],ack[7];
	char c,ch;
	char *buff=NULL,*ptr;
	short int N;
	int descrittoreSocket,msgsize;
	DIR *dir;
	struct dirent *info;

	if(argc!=2){
		perror("ERROR: Numero di parametri non conforme!");
		exit(1);

	}else{
		if(strlen(&argv[1][0])>16){
			perror("Error: Lunghezza dell'indirizzo del server non conforme!");
			exit(1);

		}else{
			stpcpy (&server[0],&argv[1][0]);
			if(gestione_dir()<0){
			  perror("ERROR: nella gestione_dir");
			  exit(1);
			}
			printf("Configurazione MailBox\n");
			printf("\nIndirizzo di Posta:");
			scanf("%s",user);
			printf("Password:");
            scanf("%s",psw);
			userpsw[0]='\0';
			 strcat(strcat(strcat(strcat(userpsw,"<r>"),user),":"),psw); /*salvo nell'array MESSAGGIO la username e password */
			while(1){
				printf("\nInserisci il carattere:\n");
				printf(">> \033[1;34mA\033[0m per inviare un messaggio!\n");
				printf(">> \033[1;34mB\033[0m per fare il download dei nuovi messaggi dal server!\n");
				printf(">> \033[1;34mC\033[0m per leggere i messaggi scaricati!\n");
				printf(">> \033[1;34mD\033[0m per eliminare i messaggi scaricati!\n");
				printf(">> \033[1;34mQ\033[0m Per chiudere il client!\n");
				fflush(stdin);
				c=getchar();
				int i=0;
				switch(c){
					case 'a':;
					case 'A':
						buffer[0]='\0';
						printf("Inserisci il destinatario:\n");
						scanf("%s",stringa);
						strcat(strcat(strcat(buffer,"Mail To:"),stringa),"\n");
                        strcat(strcat(strcat(buffer,"Mail From:"),user),"\n");
						printf("Inserisci il subject\n");
						scanf("%s",stringa);
						strcat(strcat(strcat(buffer,"Subject:"),stringa),"\n");
                        strcat(buffer,"Corpo:");
						msgsize=511-strlen(buffer);
                        printf("lunghezza di buffer=%d, indice =%d", strlen(buffer),512-strlen(buffer));
                        printf("\nInserisci il messaggio, hai a disposizione %d caratteri!\n",msgsize);
                        fflush(stdin);
						while((msgsize>0)&&((ch=getchar())!=10)){
							buffer[510-msgsize]=ch;
							msgsize--;

						}
						buffer[512-msgsize]='\0';

						/*Creo e connetto il socket*/
						printf("socket creata=%d",descrittoreSocket=CreaSocket(&server[0],porta));
						N=contaChar(user)+contaChar(psw)+5;
						ptr=buff;
						buff=realloc(buff,N*sizeof(char));
						if(buff==NULL){
							perror("ERROR on the realloc");
							exit(1);

						}
						buff[0]='\0';
						strcat(strcat(strcat(strcat(buff,"<r>"),user),":"),psw);

						/* Spedisco la lunghezza del msg */
						if (send(descrittoreSocket,(short int*)&N,sizeof(short int),0)<0){
							perror("ERROR: Impossibile mandare il messaggio.");
							chiudiSocket(descrittoreSocket);
							exit(1);

						}
						/* Spedisco username e psw e header */
						if (send(descrittoreSocket,buff,strlen(buff)+1,0)<0){
							perror("ERROR: Impossibile mandare il messaggio.");
							chiudiSocket(descrittoreSocket);
							exit(1);

						}

						/* Attendo msg di conferma dell'avvenuto login */
						recv(descrittoreSocket,ack,7*sizeof(char),0);

						/* Verifico se il login è andato a buon fine */
						if(strcmp(ack,ACK)==0){

						spedisciMessaggio(descrittoreSocket,&buffer[0]);

							/*Chiudo il socket*/
							chiudiSocket(descrittoreSocket);
							printf("\033[1;32Messaggio inviato!\033[0m\n");

						}else{
							if(strcmp(ack,NACK)==0){
								printf("Username e/o password incorretti!!\n");
								/* Reimmissione user e psw */
								login(&user[0],&psw[0]);
								break;;


							}else{
								perror("ERROR on the acknoledge");
								exit(1);
							}
						}
						break;

					case 'b':;
					case 'B':

						/*Creo e connetto il socket*/
						descrittoreSocket=creaSocket(&server[0],porta);
						N=contaChar(user)+contaChar(psw)+4;
						ptr=buff;
						buff=realloc(buff,N*sizeof(char));
						if(buff==NULL){
							perror("ERROR on the realloc");
							exit(1);

						}
						buff[0]='\0';
						strcat(strcat(strcat(strcat(buff,"<s>"),user),":"),psw);

						/* Spedisco la lunghezza del msg */
						if (send(descrittoreSocket,(short int*)&N,sizeof(short int),0)<0){
							perror("ERROR: Impossibile mandare il messaggio.");
							chiudiSocket(descrittoreSocket);
							exit(1);

						}
						/* Spedisco username e psw e header */
						if (send(descrittoreSocket,buff,strlen(buff)+1,0)<0){
							perror("ERROR: Impossibile mandare il messaggio.");
							chiudiSocket(descrittoreSocket);
							exit(1);

						}

						/* Attendo msg di conferma dell'avvenuto login */
						recv(descrittoreSocket,ack,7*sizeof(char),0);

						/* Verifico se il login è andato a buon fine */
						if(strcmp(ack,ACK)==0){

							riceviMessaggi(descrittoreSocket);

							/*Chiudo il socket*/
							chiudiSocket(descrittoreSocket);

						}else{
							if(strcmp(ack,NACK)==0){
								printf("Username e/o password incorretti!!\n");
								/* Reimmissione user e psw */
								login(&user[0],&psw[0]);
								break;;

							}else{
								perror("ERROR on the acknoledge");
								exit(1);
							}
						}


						/*Chiudo il socket*/
						chiudiSocket(descrittoreSocket);
						break;
					case 'c':;
					case 'C':
						/* Apro il descrittore della directory */
	      if (!(dir=opendir(argv[1]))) {
printf ("Impossibile aprire la directory %s\n",argv[1]);
return 1;
}
// Finché ci sono file all'interno della directory...
while (info=readdir(dir))
// ...stampa su stdout il loro nome
printf ("%s\n",info->d_name);
// Chiudi la directory
closedir(dir);



					  break;

					case 'd':;
					case 'D':

					  break;

					case 'q':;
					case 'Q':
					  free(buff);
					  return 0;
					  break;


					default:
					  printf("Scelta non ammessa!!!\n");
				}
			}
    		}
  	}
}
